package com.yycx.common.security;

import com.yycx.common.configuration.OpenCommonProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.sql.DataSource;

/**
 * token构建工具类
 *
 * @author zyf
 */
@Slf4j
public class TokenUtils {


    /**
     * 构建jwtToken转换器
     *
     * @return
     */
    public static JwtAccessTokenConverter buildJwtTokenConverter() throws Exception {
        // 使用自定义系统用户凭证转换器
        MyUserAuthenticationConverter userAuthenticationConverter = new MyUserAuthenticationConverter(SecurityConstants.DEFAULT_JWT_CLAIMS_AES_KEY);
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SecurityConstants.DEFAULT_JWT_SIGN_KEY);
        converter.setAccessTokenConverter(accessTokenConverter);
        converter.afterPropertiesSet();
        return converter;
    }

    /**
     * 构建token转换器
     *
     * @return
     */
    public static DefaultAccessTokenConverter buildAccessTokenConverter() {
        MyUserAuthenticationConverter userAuthenticationConverter = new MyUserAuthenticationConverter();
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
        return accessTokenConverter;
    }


    /**
     * 构建自定义远程Token服务类
     *
     * @param properties
     * @return
     */
    public static RemoteTokenServices buildRemoteTokenServices(OpenCommonProperties properties) {
        // 使用自定义系统用户凭证转换器
        DefaultAccessTokenConverter accessTokenConverter = buildAccessTokenConverter();
        RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setCheckTokenEndpointUrl(properties.getTokenInfoUri());
        tokenServices.setClientId(properties.getClientId());
        tokenServices.setClientSecret(properties.getClientSecret());
        tokenServices.setAccessTokenConverter(accessTokenConverter);
        log.info("buildRemoteTokenServices[{}]", tokenServices);
        return tokenServices;
    }

    /**
     * 构建资源服务器JwtToken服务类
     *
     * @param properties
     * @return
     */
    public static ResourceServerTokenServices buildJwtTokenServices(OpenCommonProperties properties) throws Exception {
        // 使用自定义系统用户凭证转换器
        DefaultAccessTokenConverter accessTokenConverter = buildAccessTokenConverter();
        OpenJwtTokenService tokenServices = new OpenJwtTokenService();
        // 这里的签名key 保持和认证中心一致
        JwtAccessTokenConverter converter = buildJwtTokenConverter();
        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
        tokenServices.setTokenStore(jwtTokenStore);
        tokenServices.setJwtAccessTokenConverter(converter);
        tokenServices.setDefaultAccessTokenConverter(accessTokenConverter);
        log.info("buildJwtTokenServices[{}]", tokenServices);
        return tokenServices;
    }

    /**
     * 构建资源服务器RedisToken服务类
     *
     * @return
     */
    public static ResourceServerTokenServices buildRedisTokenServices(RedisConnectionFactory redisConnectionFactory) throws Exception {
        OpenRedisTokenService tokenServices = new OpenRedisTokenService();
        // 这里的签名key 保持和认证中心一致
        RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        tokenServices.setTokenStore(redisTokenStore);
        log.info("buildRedisTokenServices[{}]", tokenServices);
        return tokenServices;
    }

    /**
     * 构建资源服务器JdbcToken服务类
     *
     * @return
     */
    public static ResourceServerTokenServices buildJdbcTokenServices(DataSource dataSource) throws Exception {
        OpenRedisTokenService tokenServices = new OpenRedisTokenService();
        // 这里的签名key 保持和认证中心一致
        JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);
        tokenServices.setTokenStore(jdbcTokenStore);
        log.info("buildJdbcTokenServices[{}]", tokenServices);
        return tokenServices;
    }



    /**
     * 构建RedisTokenStore(存储在redis)
     *
     * @param redisConnectionFactory
     * @return
     */
    public static RedisTokenStore buildRedisTokenStore(RedisConnectionFactory redisConnectionFactory) {
        RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        //设置token key生成规则
        redisTokenStore.setAuthenticationKeyGenerator(new MyAuthenticationKeyGenerator());
        return redisTokenStore;
    }

    /**
     * 构建JdbcTokenStore(存储在数据库)
     *
     * @param dataSource
     * @return
     */
    public static JdbcTokenStore buildJdbcTokenStore(DataSource dataSource) {
        JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);
        return jdbcTokenStore;
    }


    /**
     * 构建jwtTokenStore
     *
     * @return
     * @throws Exception
     */
    public static JwtTokenStore buildJwtTokenStore() throws Exception {
        // 这里的签名key 保持和认证中心一致
        JwtAccessTokenConverter converter = buildJwtTokenConverter();
        JwtTokenStore jwtTokenStore = new JwtTokenStore(converter);
        return jwtTokenStore;
    }
}
